using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using PickGold.Charting.ChartTypes;
using PickGold.Charting.Data;

namespace PickGold.Charting
{
    internal class Selection : IServiceProvider
    {
        private Chart _chartControl;
        private ChartPicture _chartPicture;
        private DataManager _dataManager;
        private IServiceContainer _service;

        internal Selection(IServiceContainer service)
        {
            this._service = service;
            this._chartControl = this.ChartControl;
        }

        private ArrayList GetAreaMarkers(ChartGraphics graph, ChartArea area)
        {
            ArrayList list = new ArrayList();
            if (area != null)
            {
                IList markers = this.GetMarkers(area.PlotAreaPosition.ToRectangleF(), ChartElementType.PlottingArea);
                if (this.IsChartAreaCircular(area))
                {
                    markers = this.GetMarkers(area.lastAreaPosition, ChartElementType.PlottingArea);
                }
                if (this.IsArea3D(area))
                {
                    float z = 0f;
                    Point3D[] points = new Point3D[markers.Count];
                    for (int i = 0; i < markers.Count; i++)
                    {
                        PointF tf2 = (PointF) markers[i];
                        PointF tf3 = (PointF) markers[i];
                        points[i] = new Point3D(tf2.X, tf3.Y, z);
                    }
                    area.matrix3D.TransformPoints(points);
                    for (int j = 0; j < markers.Count; j++)
                    {
                        markers[j] = points[j].PointF;
                    }
                }
                foreach (PointF tf in markers)
                {
                    list.Add(graph.GetAbsolutePoint(tf));
                }
            }
            return list;
        }

        private object GetAutoGeneratedObject(object chartObject)
        {
            DataPoint item = chartObject as DataPoint;
            if ((item != null) && (item.series != null))
            {
                string name = item.series.Name;
                int index = item.series.Points.IndexOf(item);
                if (this.ChartControl.Series.IndexOf(name) != -1)
                {
                    Series series = this.ChartControl.Series[name];
                    if (series.Points.Contains(item))
                    {
                        return chartObject;
                    }
                    if ((index >= 0) && (series.Points.Count > index))
                    {
                        return series.Points[index];
                    }
                }
            }
            Series series2 = chartObject as Series;
            if (series2 != null)
            {
                if (this.ChartControl.Series.Contains(series2))
                {
                    return chartObject;
                }
                if (this.ChartControl.Series.IndexOf(series2.Name) != -1)
                {
                    return this.ChartControl.Series[series2.Name];
                }
            }
            return chartObject;
        }

        private ArrayList GetAxisMarkers(ChartGraphics graph, Axis axis)
        {
            ArrayList list = new ArrayList();
            if (axis != null)
            {
                PointF empty = PointF.Empty;
                PointF tf2 = PointF.Empty;
                switch (axis.AxisPosition)
                {
                    case AxisPosition.Left:
                        empty.X = (float) axis.GetAxisPosition();
                        empty.Y = axis.PlotAreaPosition.Y;
                        tf2.X = (float) axis.GetAxisPosition();
                        tf2.Y = axis.PlotAreaPosition.Bottom;
                        empty.X -= axis.labelSize + axis.markSize;
                        break;

                    case AxisPosition.Right:
                        empty.X = (float) axis.GetAxisPosition();
                        empty.Y = axis.PlotAreaPosition.Y;
                        tf2.X = (float) axis.GetAxisPosition();
                        tf2.Y = axis.PlotAreaPosition.Bottom;
                        tf2.X += axis.labelSize + axis.markSize;
                        break;

                    case AxisPosition.Top:
                        empty.X = axis.PlotAreaPosition.X;
                        empty.Y = (float) axis.GetAxisPosition();
                        tf2.X = axis.PlotAreaPosition.Right;
                        tf2.Y = (float) axis.GetAxisPosition();
                        empty.Y -= axis.labelSize + axis.markSize;
                        break;

                    case AxisPosition.Bottom:
                        empty.X = axis.PlotAreaPosition.X;
                        empty.Y = (float) axis.GetAxisPosition();
                        tf2.X = axis.PlotAreaPosition.Right;
                        tf2.Y = (float) axis.GetAxisPosition();
                        tf2.Y += axis.labelSize + axis.markSize;
                        break;
                }
                if (axis.ChartArea.chartAreaIsCurcular)
                {
                    tf2.Y = axis.PlotAreaPosition.Y + (axis.PlotAreaPosition.Height / 2f);
                }
                RectangleF rect = new RectangleF(empty.X, empty.Y, tf2.X - empty.X, tf2.Y - empty.Y);
                SizeF relativeSize = graph.GetRelativeSize(new SizeF(3f, 3f));
                if ((axis.AxisPosition == AxisPosition.Top) || (axis.AxisPosition == AxisPosition.Bottom))
                {
                    rect.Inflate(2f, relativeSize.Height);
                }
                else
                {
                    rect.Inflate(relativeSize.Width, 2f);
                }
                IList markers = this.GetMarkers(rect, ChartElementType.Axis);
                ChartArea chartArea = axis.ChartArea;
                if (this.IsArea3D(chartArea))
                {
                    bool axisOnEdge = false;
                    float marksZPosition = axis.GetMarksZPosition(out axisOnEdge);
                    Point3D[] points = new Point3D[markers.Count];
                    for (int i = 0; i < markers.Count; i++)
                    {
                        PointF tf4 = (PointF) markers[i];
                        PointF tf5 = (PointF) markers[i];
                        points[i] = new Point3D(tf4.X, tf5.Y, marksZPosition);
                    }
                    axis.ChartArea.matrix3D.TransformPoints(points);
                    for (int j = 0; j < markers.Count; j++)
                    {
                        markers[j] = points[j].PointF;
                    }
                }
                foreach (PointF tf3 in markers)
                {
                    list.Add(graph.GetAbsolutePoint(tf3));
                }
            }
            return list;
        }

        internal ChartElementOutline GetChartElementOutline(object chartObject, ChartElementType elementType)
        {
            if (chartObject == null)
            {
                throw new ArgumentNullException("chartObject");
            }
            ChartElementOutline outline = new ChartElementOutline();
            chartObject = this.GetAutoGeneratedObject(chartObject);
            ArrayList markers = this.GetMarkers(chartObject, elementType);
            outline.Markers = new ReadOnlyCollection<PointF>((PointF[]) markers.ToArray(typeof(PointF)));
            outline.OutlinePath = this.GetGraphicsPath(markers, chartObject, elementType);
            return outline;
        }

        private static int GetDataPointIndex(DataPoint dataPoint)
        {
            int result = -1;
            if ((dataPoint != null) && (dataPoint.series != null))
            {
                result = dataPoint.series.Points.IndexOf(dataPoint);
                if (((result == -1) && dataPoint.IsCustomPropertySet("OriginalPointIndex")) && !int.TryParse(dataPoint.GetCustomProperty("OriginalPointIndex"), out result))
                {
                    return -1;
                }
            }
            return result;
        }

        private GraphicsPath GetGraphicsPath(IList markers, object chartObject, ChartElementType elementType)
        {
            bool flag = false;
            ChartArea area = chartObject as ChartArea;
            if ((area != null) && (elementType == ChartElementType.PlottingArea))
            {
                flag = this.IsArea3D(area);
            }
            if ((((elementType == ChartElementType.DataPoint) || (elementType == ChartElementType.Gridlines)) || ((elementType == ChartElementType.StripLines) || (elementType == ChartElementType.TickMarks))) || flag)
            {
                return null;
            }
            GraphicsPath path = new GraphicsPath();
            PointF[] array = new PointF[markers.Count];
            markers.CopyTo(array, 0);
            if (array.Length > 3)
            {
                if (elementType == ChartElementType.DataPointLabel)
                {
                    for (int i = 0; i < array.Length; i += 4)
                    {
                        RectangleF ef = RectangleF.FromLTRB(array[i].X, array[i].Y, array[i + 2].X, array[i + 2].Y);
                        path.Reset();
                        path.AddRectangle(Rectangle.Round(ef));
                    }
                    return path;
                }
                if (array.Length == 4)
                {
                    Point[] points = new Point[array.Length];
                    for (int j = 0; j < array.Length; j++)
                    {
                        points[j] = Point.Round(array[j]);
                    }
                    path.AddPolygon(points);
                    return path;
                }
                path.AddPolygon(array);
            }
            return path;
        }

        internal HitTestResult GetHitTestResult(string seriesName, int pointIndex, ChartElementType type, object obj, object subObject)
        {
            HitTestResult result = new HitTestResult();
            Chart chartControl = this.ChartControl;
            if (seriesName.Length > 0)
            {
                result.Series = chartControl.Series[seriesName];
            }
            result.Object = obj;
            result.SubObject = subObject;
            result.PointIndex = pointIndex;
            result.ChartElementType = type;
            switch (type)
            {
                case ChartElementType.Title:
                    result.Axis = null;
                    result.ChartArea = null;
                    return result;

                case ChartElementType.PlottingArea:
                {
                    ChartArea area = (ChartArea) obj;
                    result.Axis = null;
                    result.ChartArea = area;
                    return result;
                }
                case ChartElementType.Axis:
                {
                    Axis axis = (Axis) obj;
                    result.Axis = axis;
                    if (axis != null)
                    {
                        result.ChartArea = axis.ChartArea;
                    }
                    return result;
                }
                case ChartElementType.TickMarks:
                {
                    TickMark mark = (TickMark) obj;
                    result.Axis = mark.Axis;
                    if (mark.Axis != null)
                    {
                        result.ChartArea = mark.Axis.ChartArea;
                    }
                    return result;
                }
                case ChartElementType.Gridlines:
                {
                    Grid grid = (Grid) obj;
                    result.Axis = grid.Axis;
                    if (grid.Axis != null)
                    {
                        result.ChartArea = grid.Axis.ChartArea;
                    }
                    return result;
                }
                case ChartElementType.StripLines:
                {
                    StripLine line = (StripLine) obj;
                    result.Axis = line.Axis;
                    if (line.Axis != null)
                    {
                        result.ChartArea = line.Axis.ChartArea;
                    }
                    return result;
                }
                case ChartElementType.AxisLabelImage:
                    if (obj is CustomLabel)
                    {
                        CustomLabel label2 = (CustomLabel) obj;
                        result.Axis = label2.Axis;
                        result.ChartArea = (label2.Axis != null) ? label2.Axis.ChartArea : null;
                    }
                    return result;

                case ChartElementType.AxisLabels:
                    if (obj is CustomLabel)
                    {
                        CustomLabel label = (CustomLabel) obj;
                        result.Axis = label.Axis;
                        result.ChartArea = (label.Axis != null) ? label.Axis.ChartArea : null;
                    }
                    return result;

                case ChartElementType.AxisTitle:
                    if (obj is Axis)
                    {
                        result.Axis = (Axis) obj;
                        result.ChartArea = result.Axis.ChartArea;
                    }
                    return result;

                case ChartElementType.DataPoint:
                    if ((chartControl.Series.IndexOf(seriesName) >= 0) && (pointIndex < chartControl.Series[seriesName].Points.Count))
                    {
                        DataPoint point = chartControl.Series[seriesName].Points[pointIndex];
                        result.Axis = null;
                        result.ChartArea = chartControl.ChartAreas[point.series.ChartArea];
                        result.Object = point;
                    }
                    return result;

                case ChartElementType.DataPointLabel:
                    if ((chartControl.Series.IndexOf(seriesName) >= 0) && (pointIndex < chartControl.Series[seriesName].Points.Count))
                    {
                        DataPoint point2 = chartControl.Series[seriesName].Points[pointIndex];
                        result.Axis = null;
                        result.ChartArea = chartControl.ChartAreas[point2.series.ChartArea];
                        result.Object = point2;
                    }
                    return result;

                case ChartElementType.LegendArea:
                    result.Axis = null;
                    result.ChartArea = null;
                    return result;

                case ChartElementType.LegendTitle:
                case ChartElementType.LegendHeader:
                    return result;

                case ChartElementType.LegendItem:
                    result.PointIndex = ((LegendItem) obj).SeriesPointIndex;
                    result.Axis = null;
                    result.ChartArea = null;
                    return result;

                case ChartElementType.Annotation:
                    result.Axis = null;
                    result.ChartArea = null;
                    return result;
            }
            return result;
        }

        private RectangleF GetHotRegionRectangle(HotRegion rgn, RectangleF unionWith, ChartElementType elementType)
        {
            RectangleF bounds;
            if (rgn.Path != null)
            {
                bounds = rgn.Path.GetBounds();
            }
            else
            {
                bounds = rgn.BoundingRectangle;
            }
            if (rgn.RelativeCoordinates)
            {
                bounds = this.Graph.GetAbsoluteRectangle(bounds);
            }
            if (elementType == ChartElementType.AxisLabels)
            {
                if (bounds.Width > bounds.Height)
                {
                    bounds.Inflate(-5f, -2f);
                }
                else if (bounds.Width < bounds.Height)
                {
                    bounds.Inflate(-2f, -5f);
                }
            }
            if (!unionWith.IsEmpty)
            {
                return RectangleF.Union(unionWith, bounds);
            }
            return bounds;
        }

        private HotRegion[] GetHotRegions(object cntxObj, ChartElementType elementType)
        {
            ArrayList list = new ArrayList();
            HotRegionsList hotRegionsList = this.ChartPicture.Common.HotRegionsList;
            string name = string.Empty;
            int dataPointIndex = -1;
            for (int i = hotRegionsList.List.Count - 1; i >= 0; i--)
            {
                CustomLabel selectedObject;
                DataPointCollection points;
                HotRegion region = (HotRegion) hotRegionsList.List[i];
                if (region.Type != elementType)
                {
                    continue;
                }
                switch (region.Type)
                {
                    case ChartElementType.AxisLabelImage:
                    case ChartElementType.AxisLabels:
                    {
                        CustomLabel label = cntxObj as CustomLabel;
                        selectedObject = region.SelectedObject as CustomLabel;
                        if (label == null)
                        {
                            break;
                        }
                        if ((((label != null) && (selectedObject != null)) && ((label.Axis == selectedObject.Axis) && (label.FromPosition == selectedObject.FromPosition))) && (((label.ToPosition == selectedObject.ToPosition) && (label.RowIndex == selectedObject.RowIndex)) && (region.Path == null)))
                        {
                            list.Add(region);
                        }
                        continue;
                    }
                    case ChartElementType.DataPoint:
                    case ChartElementType.DataPointLabel:
                    {
                        DataPoint dataPoint = cntxObj as DataPoint;
                        if (dataPoint == null)
                        {
                            goto Label_01E4;
                        }
                        if (string.IsNullOrEmpty(name) || (dataPointIndex == -1))
                        {
                            name = dataPoint.series.Name;
                            dataPointIndex = GetDataPointIndex(dataPoint);
                        }
                        if ((region.PointIndex == dataPointIndex) && (region.SeriesName == name))
                        {
                            list.Add(region);
                        }
                        continue;
                    }
                    case ChartElementType.LegendItem:
                    {
                        LegendItem item = cntxObj as LegendItem;
                        if ((item != null) && (((LegendItem) region.SelectedObject).Name == item.Name))
                        {
                            list.Add(region);
                        }
                        continue;
                    }
                    default:
                        goto Label_0233;
                }
                Axis axis = cntxObj as Axis;
                if (((axis != null) && (axis == selectedObject.Axis)) && (region.Path == null))
                {
                    list.Add(region);
                }
                continue;
            Label_01E4:
                points = cntxObj as DataPointCollection;
                if (points != null)
                {
                    cntxObj = points.series;
                }
                Series series = cntxObj as Series;
                if (series != null)
                {
                    if (string.IsNullOrEmpty(name) || (dataPointIndex == -1))
                    {
                        name = series.Name;
                    }
                    if (region.SeriesName == name)
                    {
                        list.Add(region);
                    }
                }
                continue;
            Label_0233:
                if (region.SelectedObject == cntxObj)
                {
                    list.Add(region);
                }
            }
            return (HotRegion[]) list.ToArray(typeof(HotRegion));
        }

        private ArrayList GetMarkers(RectangleF rect, bool addAdditionalMarkers)
        {
            ArrayList list = new ArrayList();
            if (!addAdditionalMarkers)
            {
                if ((rect.Width > 0f) && (rect.Height > 0f))
                {
                    list.Add(new PointF(rect.Left, rect.Top));
                    list.Add(new PointF(rect.Right, rect.Top));
                    list.Add(new PointF(rect.Right, rect.Bottom));
                    list.Add(new PointF(rect.Left, rect.Bottom));
                    return list;
                }
                if (rect.Width > 0f)
                {
                    list.Add(new PointF(rect.Left, rect.Top));
                    list.Add(new PointF(rect.Right, rect.Top));
                    return list;
                }
                if (rect.Height > 0f)
                {
                    list.Add(new PointF(rect.Left, rect.Top));
                    list.Add(new PointF(rect.Left, rect.Bottom));
                }
                return list;
            }
            if (rect.Width > 0f)
            {
                list.Add(new PointF(rect.Left, rect.Top));
                if (rect.Width > 30f)
                {
                    list.Add(new PointF(rect.Left + (rect.Width / 2f), rect.Top));
                }
                list.Add(new PointF(rect.Right, rect.Top));
                if (rect.Height > 30f)
                {
                    list.Add(new PointF(rect.Right, rect.Top + (rect.Height / 2f)));
                }
                list.Add(new PointF(rect.Right, rect.Bottom));
                if (rect.Width > 30f)
                {
                    list.Add(new PointF(rect.Left + (rect.Width / 2f), rect.Bottom));
                }
                list.Add(new PointF(rect.Left, rect.Bottom));
                if (rect.Height > 30f)
                {
                    list.Add(new PointF(rect.Left, rect.Top + (rect.Height / 2f)));
                }
                return list;
            }
            if (rect.Width > 0f)
            {
                list.Add(new PointF(rect.Left, rect.Top));
                if (rect.Width > 30f)
                {
                    list.Add(new PointF(rect.Left + (rect.Width / 2f), rect.Top));
                }
                list.Add(new PointF(rect.Right, rect.Top));
                return list;
            }
            if (rect.Height > 0f)
            {
                list.Add(new PointF(rect.Left, rect.Bottom));
                if (rect.Height > 30f)
                {
                    list.Add(new PointF(rect.Left, rect.Top + (rect.Height / 2f)));
                }
                list.Add(new PointF(rect.Left, rect.Top));
            }
            return list;
        }

        private ArrayList GetMarkers(RectangleF rect, ChartElementType elementType)
        {
            if (elementType.ToString().StartsWith("Legend", StringComparison.Ordinal) || elementType.ToString().StartsWith("Title", StringComparison.Ordinal))
            {
                rect.Inflate(4f, 4f);
            }
            if (elementType.ToString().StartsWith("PlottingArea", StringComparison.Ordinal))
            {
                SizeF relativeSize = this.Graph.GetRelativeSize(new SizeF(4f, 4f));
                rect.Inflate(relativeSize.Width, relativeSize.Height);
            }
            if ((elementType != ChartElementType.Nothing) && (elementType != ChartElementType.PlottingArea))
            {
                return this.GetMarkers(rect, false);
            }
            return this.GetMarkers(rect, true);
        }

        private ArrayList GetMarkers(object chartObject, ChartElementType elementType)
        {
            ChartArea area = chartObject as ChartArea;
            if (area != null)
            {
                return this.GetAreaMarkers(this.Graph, area);
            }
            Axis axis = chartObject as Axis;
            if (axis != null)
            {
                if (((elementType != ChartElementType.AxisLabelImage) && (elementType != ChartElementType.AxisLabels)) && (elementType != ChartElementType.AxisTitle))
                {
                    return this.GetAxisMarkers(this.Graph, axis);
                }
                return this.GetMarkersFromRegions(chartObject, elementType);
            }
            if (chartObject is DataPoint)
            {
                return this.GetMarkersFromRegions(chartObject, elementType);
            }
            Series series = chartObject as Series;
            if (series == null)
            {
                return this.GetMarkersFromRegions(chartObject, elementType);
            }
            if (elementType == ChartElementType.DataPointLabel)
            {
                return this.GetMarkersFromRegions(chartObject, elementType);
            }
            return this.GetSeriesMarkers(series);
        }

        private ArrayList GetMarkersFromRegions(object chartObject, ChartElementType elementType)
        {
            RectangleF bounds;
            ArrayList list = new ArrayList();
            HotRegion[] hotRegions = this.GetHotRegions(chartObject, elementType);
            ChartGraphics graph = this.Graph;
            Grid grid = chartObject as Grid;
            if (grid != null)
            {
                foreach (HotRegion region in hotRegions)
                {
                    if (!this.IsArea3D(grid.Axis.ChartArea))
                    {
                        if (this.IsChartAreaCircular(grid.Axis.ChartArea))
                        {
                            GraphicsPathIterator iterator = new GraphicsPathIterator(region.Path);
                            if (iterator.SubpathCount > 1)
                            {
                                GraphicsPath path = new GraphicsPath();
                                while (iterator.NextMarker(path) > 0)
                                {
                                    bounds = path.GetBounds();
                                    list.Add(new PointF(bounds.Left + (bounds.Width / 2f), bounds.Top));
                                    list.Add(new PointF(bounds.Right, bounds.Top + (bounds.Height / 2f)));
                                    list.Add(new PointF(bounds.Right - (bounds.Width / 2f), bounds.Bottom));
                                    list.Add(new PointF(bounds.Left, bounds.Bottom - (bounds.Height / 2f)));
                                    path.Reset();
                                }
                            }
                        }
                        else
                        {
                            bounds = this.GetHotRegionRectangle(region, RectangleF.Empty, elementType);
                            if (grid != null)
                            {
                                if ((grid.GetAxis().AxisPosition == AxisPosition.Bottom) || (grid.GetAxis().AxisPosition == AxisPosition.Top))
                                {
                                    bounds.Offset(bounds.Width / 2f, 0f);
                                    bounds.Width = 0f;
                                }
                                else
                                {
                                    bounds.Offset(0f, bounds.Height / 2f);
                                    bounds.Height = 0f;
                                }
                            }
                            list.AddRange(this.GetMarkers(bounds, false));
                        }
                    }
                    else
                    {
                        PointF[] pathPoints = region.Path.PathPoints;
                        for (int i = 0; i < (pathPoints.Length - 3); i += 4)
                        {
                            PointF tf = new PointF((pathPoints[i].X + pathPoints[i + 3].X) / 2f, (pathPoints[i].Y + pathPoints[i + 3].Y) / 2f);
                            PointF tf2 = new PointF((pathPoints[i + 1].X + pathPoints[i + 2].X) / 2f, (pathPoints[i + 1].Y + pathPoints[i + 2].Y) / 2f);
                            list.Add(graph.GetAbsolutePoint(tf));
                            list.Add(graph.GetAbsolutePoint(tf2));
                        }
                    }
                }
                return list;
            }
            DataPoint point = chartObject as DataPoint;
            if ((point != null) && (elementType != ChartElementType.DataPointLabel))
            {
                bounds = Rectangle.Empty;
                Series series = point.series;
                if (this.ChartControl.ChartAreas.IndexOf(series.ChartArea) != -1)
                {
                    ChartArea chartArea = this.ChartControl.ChartAreas[series.ChartArea];
                    PointF tf3 = this.Transform3D(chartArea, point);
                    if (!float.IsNaN(tf3.X) && !float.IsNaN(tf3.Y))
                    {
                        list.Add(graph.GetAbsolutePoint(tf3));
                    }
                }
                return list;
            }
            Axis axis = chartObject as Axis;
            if ((axis != null) && (elementType == ChartElementType.AxisTitle))
            {
                foreach (HotRegion region2 in hotRegions)
                {
                    if (!this.IsArea3D(axis.ChartArea))
                    {
                        bounds = this.GetHotRegionRectangle(region2, RectangleF.Empty, elementType);
                        list.AddRange(this.GetMarkers(bounds, elementType));
                    }
                    else
                    {
                        PointF[] c = region2.Path.PathPoints;
                        list.AddRange(c);
                    }
                }
                return list;
            }
            if (chartObject is LegendItem)
            {
                bounds = Rectangle.Empty;
                foreach (HotRegion region3 in hotRegions)
                {
                    bounds = this.GetHotRegionRectangle(region3, bounds, elementType);
                }
                if (!bounds.IsEmpty)
                {
                    list.AddRange(this.GetMarkers(bounds, elementType));
                }
                return list;
            }
            if (chartObject is Annotation)
            {
                bounds = Rectangle.Empty;
                foreach (HotRegion region4 in hotRegions)
                {
                    bounds = this.GetHotRegionRectangle(region4, bounds, elementType);
                }
                if (!bounds.IsEmpty)
                {
                    list.AddRange(this.GetMarkers(bounds, elementType));
                }
                return list;
            }
            foreach (HotRegion region5 in hotRegions)
            {
                bounds = this.GetHotRegionRectangle(region5, RectangleF.Empty, elementType);
                list.AddRange(this.GetMarkers(bounds, elementType));
            }
            return list;
        }

        private ArrayList GetRegionMarkers(GraphicsPath path)
        {
            return new ArrayList(path.PathPoints);
        }

        private ArrayList GetSeriesMarkers(Series series)
        {
            ArrayList list = new ArrayList();
            if (series != null)
            {
                string chartArea = series.ChartArea;
                if (string.IsNullOrEmpty(chartArea))
                {
                    chartArea = this.ChartPicture.ChartAreas.DefaultNameReference;
                }
                if ((this.ChartPicture.ChartAreas.IndexOf(chartArea) == -1) || !series.Enabled)
                {
                    return list;
                }
                ChartArea area = this.ChartPicture.ChartAreas[chartArea];
                if (this.ChartControl.Series.IndexOf(series.Name) != -1)
                {
                    series = this.ChartControl.Series[series.Name];
                }
                DataPointCollection fakeDataPoints = series.Points;
                if (fakeDataPoints.Count == 0)
                {
                    fakeDataPoints = series.fakeDataPoints;
                }
                foreach (DataPoint point in fakeDataPoints)
                {
                    PointF tf = this.Transform3D(area, point);
                    if (!float.IsNaN(tf.X) && !float.IsNaN(tf.Y))
                    {
                        list.Add(this.Graph.GetAbsolutePoint(tf));
                    }
                }
            }
            return list;
        }

        internal HitTestResult HitTest(int x, int y)
        {
            return this.HitTest(x, y, false, new ChartElementType[0])[0];
        }

        public HitTestResult HitTest(int x, int y, bool ignoreTransparent)
        {
            return this.HitTest(x, y, ignoreTransparent, new ChartElementType[0])[0];
        }

        public HitTestResult HitTest(int x, int y, ChartElementType requestedElement)
        {
            return this.HitTest(x, y, false, new ChartElementType[] { requestedElement })[0];
        }

        internal HitTestResult[] HitTest(int x, int y, bool ignoreTransparent, params ChartElementType[] requestedElementTypes)
        {
            List<HitTestResult> list = new List<HitTestResult>();
            ArrayList list2 = this.ChartPicture.Common.HotRegionsList.List;
            if (list2.Count == 0)
            {
                this.ChartPicture.PaintOffScreen();
            }
            string str = string.Empty;
            if (requestedElementTypes.Length > 0)
            {
                StringBuilder builder = new StringBuilder();
                foreach (ChartElementType type in requestedElementTypes)
                {
                    builder.Append(type.ToString() + ";");
                }
                str = builder.ToString();
            }
            RectangleF rectangle = new RectangleF((float) (x - 1), (float) (y - 1), 2f, 2f);
            float num3 = this.Graph.GetRelativePoint(new PointF((float) x, (float) y)).X;
            float num4 = this.Graph.GetRelativePoint(new PointF((float) x, (float) y)).Y;
            RectangleF relativeRectangle = this.Graph.GetRelativeRectangle(rectangle);
            for (int i = list2.Count - 1; i >= 0; i--)
            {
                HotRegion region = (HotRegion) list2[i];
                if (string.IsNullOrEmpty(str) || (str.IndexOf(region.Type.ToString() + ";", StringComparison.Ordinal) != -1))
                {
                    float num;
                    float num2;
                    RectangleF ef;
                    if (region.RelativeCoordinates)
                    {
                        num = num3;
                        num2 = num4;
                        ef = relativeRectangle;
                    }
                    else
                    {
                        num = x;
                        num2 = y;
                        ef = rectangle;
                    }
                    if ((((region.SeriesName.Length <= 0) || ((this.ChartControl.Series.IndexOf(region.SeriesName) >= 0) && (region.PointIndex < this.ChartControl.Series[region.SeriesName].Points.Count))) && (!ignoreTransparent || !this.IsElementTransparent(region))) && region.BoundingRectangle.IntersectsWith(ef))
                    {
                        bool flag = false;
                        if (region.Path != null)
                        {
                            GraphicsPathIterator iterator = new GraphicsPathIterator(region.Path);
                            if (iterator.SubpathCount > 1)
                            {
                                GraphicsPath path = new GraphicsPath();
                                while ((iterator.NextMarker(path) > 0) && !flag)
                                {
                                    if (path.IsVisible(num, num2))
                                    {
                                        flag = true;
                                    }
                                    path.Reset();
                                }
                            }
                            else if (region.Path.IsVisible(num, num2))
                            {
                                flag = true;
                            }
                        }
                        else
                        {
                            flag = true;
                        }
                        if (flag)
                        {
                            HitTestResult hitTestToAdd = this.GetHitTestResult(region.SeriesName, region.PointIndex, region.Type, region.SelectedObject, region.SelectedSubObject);
                            if (list.FindIndex(delegate (HitTestResult test) {
                                return (((test.ChartElementType == hitTestToAdd.ChartElementType) && (test.Object == hitTestToAdd.Object)) && ((test.SubObject == hitTestToAdd.SubObject) && (test.Series == hitTestToAdd.Series))) && (test.PointIndex == hitTestToAdd.PointIndex);
                            }) == -1)
                            {
                                list.Add(hitTestToAdd);
                            }
                        }
                    }
                }
            }
            if (list.Count == 0)
            {
                list.Add(this.GetHitTestResult(string.Empty, 0, ChartElementType.Nothing, null, null));
            }
            return list.ToArray();
        }

        private bool IsArea3D(ChartArea area)
        {
            return (((area.Area3DStyle.Enable3D && !this.IsChartAreaCircular(area)) && (area.matrix3D != null)) && area.matrix3D.IsInitialized());
        }

        private bool IsChartAreaCircular(ChartArea area)
        {
            foreach (object obj2 in area.ChartTypes)
            {
                IChartType chartType = area.Common.ChartTypeRegistry.GetChartType(obj2.ToString());
                if ((chartType != null) && (chartType.CircularChartArea || !chartType.RequireAxes))
                {
                    return true;
                }
            }
            return false;
        }

        private bool IsElementTransparent(HotRegion region)
        {
            bool flag = false;
            if (region.Type == ChartElementType.DataPoint)
            {
                if (this.ChartControl != null)
                {
                    DataPoint point = region.SelectedObject as DataPoint;
                    if (region.SeriesName.Length > 0)
                    {
                        point = this.ChartControl.Series[region.SeriesName].Points[region.PointIndex];
                    }
                    if ((point != null) && (point.Color == Color.Transparent))
                    {
                        flag = true;
                    }
                }
                return flag;
            }
            if (region.SelectedObject is Axis)
            {
                if (((Axis) region.SelectedObject).LineColor == Color.Transparent)
                {
                    flag = true;
                }
                return flag;
            }
            if (region.SelectedObject is ChartArea)
            {
                if (((ChartArea) region.SelectedObject).BackColor == Color.Transparent)
                {
                    flag = true;
                }
                return flag;
            }
            if (region.SelectedObject is Legend)
            {
                if (((Legend) region.SelectedObject).BackColor == Color.Transparent)
                {
                    flag = true;
                }
                return flag;
            }
            if (region.SelectedObject is Grid)
            {
                if (((Grid) region.SelectedObject).LineColor == Color.Transparent)
                {
                    flag = true;
                }
                return flag;
            }
            if (region.SelectedObject is StripLine)
            {
                if (((StripLine) region.SelectedObject).BackColor == Color.Transparent)
                {
                    flag = true;
                }
                return flag;
            }
            if (region.SelectedObject is TickMark)
            {
                if (((TickMark) region.SelectedObject).LineColor == Color.Transparent)
                {
                    flag = true;
                }
                return flag;
            }
            if (!(region.SelectedObject is Title))
            {
                return flag;
            }
            Title selectedObject = (Title) region.SelectedObject;
            if ((selectedObject.Text.Length != 0) && !(selectedObject.ForeColor == Color.Transparent))
            {
                return flag;
            }
            if (!(selectedObject.BackColor == Color.Transparent) && !selectedObject.BackColor.IsEmpty)
            {
                return flag;
            }
            return true;
        }

        object IServiceProvider.GetService(Type serviceType)
        {
            if (serviceType == typeof(Selection))
            {
                return this;
            }
            if (this._service != null)
            {
                return this._service.GetService(serviceType);
            }
            return null;
        }

        private PointF Transform3D(ChartArea chartArea, DataPoint point)
        {
            if ((chartArea == null) || !this.IsArea3D(chartArea))
            {
                return point.positionRel;
            }
            float areaSceneDepth = chartArea.areaSceneDepth;
            if ((point != null) && (point.series != null))
            {
                float depth = 0f;
                chartArea.GetSeriesZPositionAndDepth(point.series, out depth, out areaSceneDepth);
                areaSceneDepth += depth / 2f;
            }
            PointF positionRel = point.positionRel;
            Point3D[] points = new Point3D[] { new Point3D(positionRel.X, positionRel.Y, areaSceneDepth) };
            chartArea.matrix3D.TransformPoints(points);
            return points[0].PointF;
        }

        internal Chart ChartControl
        {
            get
            {
                if ((this._chartControl == null) && (this.ChartPicture != null))
                {
                    this._chartControl = this.ChartPicture.Chart;
                }
                return this._chartControl;
            }
        }

        internal ChartPicture ChartPicture
        {
            get
            {
                if (this._chartPicture == null)
                {
                    this._chartPicture = ((IServiceProvider) this).GetService(typeof(ChartImage)) as ChartPicture;
                    if (this._chartPicture == null)
                    {
                        this._chartPicture = ((IServiceProvider) this).GetService(typeof(ChartPicture)) as ChartPicture;
                    }
                }
                return this._chartPicture;
            }
        }

        internal DataManager DataManager
        {
            get
            {
                if (this._dataManager == null)
                {
                    this._dataManager = ((IServiceProvider) this).GetService(typeof(DataManager)) as DataManager;
                }
                return this._dataManager;
            }
        }

        internal ChartGraphics Graph
        {
            get
            {
                if (this.ChartPicture != null)
                {
                    return this.ChartPicture.Common.graph;
                }
                return null;
            }
        }
    }
}

